package ace.module.stock.core.impl.service.impl;

import ace.cmp.util.AceAssertUtils;
import ace.module.common.api.model.input.TenantAndAppTypeInput;
import ace.module.stock.api.enums.WmsSalesQuantityRecordActionTypeEnum;
import ace.module.stock.api.model.dto.WmsSalesQuantityDto;
import ace.module.stock.api.model.input.WmsBizInitInput;
import ace.module.stock.api.model.input.WmsBizParentIdInput;
import ace.module.stock.api.model.input.WmsBizUniqueIdInput;
import ace.module.stock.api.model.input.WmsSalesActionRecordInput;
import ace.module.stock.api.model.input.WmsSalesActionRecordWithBatchSnInput;
import ace.module.stock.api.model.input.WmsSalesActionTypeRecordInput;
import ace.module.stock.api.model.input.WmsSalesActionTypeRecordWithBatchSnInput;
import ace.module.stock.api.model.input.WmsSalesReverseBatchSnInput;
import ace.module.stock.core.impl.dao.aggregate.WmsStockAggregate;
import ace.module.stock.core.impl.dao.aggregate.helper.WmsSalesQuantityAggregateHelper;
import ace.module.stock.core.impl.dao.aggregate.helper.WmsStockRecordAggregateHelper;
import ace.module.stock.core.impl.dao.entity.WmsApplication;
import ace.module.stock.core.impl.dao.entity.WmsStock;
import ace.module.stock.core.impl.dao.entity.WmsStockBatchRecord;
import ace.module.stock.core.impl.dao.entity.WmsStockRecord;
import ace.module.stock.core.impl.manager.WmsApplicationManager;
import ace.module.stock.core.impl.manager.WmsSalesQuantityBatchRecordManager;
import ace.module.stock.core.impl.manager.WmsSalesQuantityManager;
import ace.module.stock.core.impl.manager.WmsSalesQuantityRecordManager;
import ace.module.stock.core.impl.manager.WmsStockBatchRecordManager;
import ace.module.stock.core.impl.manager.WmsStockManager;
import ace.module.stock.core.impl.manager.WmsStockRecordManager;
import ace.module.stock.core.impl.service.WmsSalesQuantityService;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.NotImplementedException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

/**
 * .
 *
 * @author Caspar
 */
@Slf4j
@AllArgsConstructor
@Component
public class WmsSalesQuantityServiceImpl implements WmsSalesQuantityService {

  private final WmsSalesQuantityManager wmsSalesQuantityManager;
  private final WmsSalesQuantityRecordManager wmsSalesQuantityRecordManager;
  private final WmsSalesQuantityBatchRecordManager wmsSalesQuantityBatchRecordManager;
  private final WmsApplicationManager wmsApplicationManager;
  private final WmsSalesQuantityAggregateHelper wmsSalesQuantityAggregateHelper;
  private final WmsStockBatchRecordManager wmsStockBatchRecordManager;
  private final WmsStockRecordAggregateHelper wmsStockRecordAggregateHelper;
  private final WmsStockRecordManager wmsStockRecordManager;
  private final WmsStockManager wmsStockManager;
  private final WmsStockAggregate wmsStockAggregate;

  @Override
  public void initOrNone(TenantAndAppTypeInput<WmsBizInitInput> input) {
    WmsApplication wmsApplication = wmsApplicationManager.getAndCheckByOutIdAndOutType(input.getTenantId().toString(), input.getType());

    wmsSalesQuantityManager.initOrNone(wmsApplication, input.getData());
  }

  @Override
  public String add(TenantAndAppTypeInput<WmsSalesActionRecordWithBatchSnInput> input) {
    WmsApplication wmsApplication = this.wmsApplicationManager.getAndCheckByOutIdAndOutType(input.getTenantId().toString(), input.getType());
    List<WmsSalesActionRecordInput> actionRecordInputs = input.getData().getActionRecordInputs();
    String batchSn = this.wmsSalesQuantityBatchRecordManager.getDefaultSnOrNewSn(input.getData().getBatchSn());
    return this.addSkuStockAndAutoCalcRecursionParentStocks(wmsApplication, batchSn, actionRecordInputs);
  }

  @Override
  public String subtract(TenantAndAppTypeInput<WmsSalesActionRecordWithBatchSnInput> input) {
    return null;
  }

  @Override
  public String modify(TenantAndAppTypeInput<WmsSalesActionTypeRecordWithBatchSnInput> input) {
    return null;
  }

  @Override
  public String reverse(TenantAndAppTypeInput<WmsSalesReverseBatchSnInput> input) {
    return null;
  }

  @Override
  public List<WmsSalesQuantityDto> getDtoByBizUniqueIdIn(TenantAndAppTypeInput<List<WmsBizUniqueIdInput>> input) {
    WmsApplication wmsApplication = wmsApplicationManager.getByOutIdAndOutType(input.getTenantId().toString(), input.getType());

    if (Objects.isNull(wmsApplication)) {
      return new ArrayList<>();
    }

    return wmsSalesQuantityManager.getDtoListByWmsAppIdAndBizUniqueIdIn(wmsApplication.getId(), input.getData());
  }

  @Override
  public List<WmsSalesQuantityDto> getDtoByBizParentIdIn(TenantAndAppTypeInput<WmsBizParentIdInput> bizParentIdInput) {
    WmsApplication wmsApplication = wmsApplicationManager.getByOutIdAndOutType(bizParentIdInput.getTenantId().toString(), bizParentIdInput.getType());

    if (Objects.isNull(wmsApplication)) {
      return new ArrayList<>();
    }

    return wmsSalesQuantityManager.getDtoListByWmsAppIdAndBizParentId(wmsApplication.getId(), bizParentIdInput.getData());
  }

  private String subtractSkuStockAndAutoCalcRecursionParentStocks(WmsApplication wmsApplication, String batchSn, List<WmsSalesActionRecordInput> actionRecordInputs) {
    return this.addOrSubtractSkuStockAndAutoCalcRecursionParentStocks(wmsApplication, batchSn, WmsSalesQuantityRecordActionTypeEnum.SUBTRACT, actionRecordInputs);
  }

  private String addSkuStockAndAutoCalcRecursionParentStocks(WmsApplication wmsApplication, String batchSn, List<WmsSalesActionRecordInput> actionRecordInputs) {
    return this.addOrSubtractSkuStockAndAutoCalcRecursionParentStocks(wmsApplication, batchSn, WmsSalesQuantityRecordActionTypeEnum.ADD, actionRecordInputs);
  }

  private String addOrSubtractSkuStockAndAutoCalcRecursionParentStocks(
      WmsApplication wmsApplication,
      String batchSn,
      WmsSalesQuantityRecordActionTypeEnum actionTypeEnum,
      List<WmsSalesActionRecordInput> actionRecordInputs) {
    AceAssertUtils.isFalse(
        WmsSalesQuantityRecordActionTypeEnum.ADD.equals(actionTypeEnum) || WmsSalesQuantityRecordActionTypeEnum.SUBTRACT.equals(actionTypeEnum),
        "仅支持增加与扣减操作"
    );

    List<WmsSalesActionTypeRecordInput> skuActionRecordWithTypeInputs = this.convertWmsSalesActionRecordWithTypeInputs(actionRecordInputs, actionTypeEnum);

    this.modifySkuStockAndAutoCalcRecursionParentStocks(wmsApplication, batchSn, skuActionRecordWithTypeInputs);

    return batchSn;
  }

  private String modifySkuStockAndAutoCalcRecursionParentStocks(
      WmsApplication wmsApplication,
      String batchSn,
      List<WmsSalesActionTypeRecordInput> skuActionRecordWithTypeInputs
  ) {
    throw new NotImplementedException();
//    AceAssertUtils.isEmpty(skuActionRecordWithTypeInputs, "销量操作不能为空");
//    AceAssertUtils.isNull(wmsApplication, "仓库应用不能为空");
//    AceAssertUtils.isEmpty(batchSn, "操作批次流水号不能为空");
//
//    Long wmsAppId = wmsApplication.getId();
//
//    List<Long> skuObjectIdInputs = skuActionRecordWithTypeInputs.stream()
//        .map(WmsStockActionRecordInput::getObjectId)
//        .collect(Collectors.toList());
//
//    List<WmsSalesQuantity> skuAndAllRecursionParents = this.wmsSalesQuantityManager.getSkuAndAllRecursionParentsByWmsAppIdAndObjectIdIn(wmsAppId, skuObjectIdInputs);
//
//    this.wmsSalesQuantityManager.checkNotContainsAllByObjectId(skuAndAllRecursionParents, skuObjectIdInputs);
//
//    List<WmsSalesQuantity> skuWmsSalesQuantities = this.wmsSalesQuantityAggregateHelper.getSkus(skuAndAllRecursionParents);
//
//    this.wmsStockBatchRecordManager.checkNotExistBatchSnByWmsApIdAndBatchSn(wmsAppId, batchSn);
//
//    List<WmsStockRecord> skuWmsStockRecords = this.wmsStockRecordManager.buildModifyRecord(wmsAppId, batchSn, skuWmsSalesQuantities, skuActionRecordWithTypeInputs);
//
//    WmsStockBatchRecord wmsStockBatchRecord = this.wmsStockBatchRecordManager.build(wmsAppId, batchSn);
//
//    this.wmsStockAggregate.modifySkuStockAndCalcRecursionParentStocks(skuAndAllRecursionParents, wmsStockBatchRecord, skuWmsStockRecords);
//
//    return batchSn;
  }

  private List<WmsSalesActionTypeRecordInput> convertWmsSalesActionRecordWithTypeInputs(List<WmsSalesActionRecordInput> actionRecordInputs, WmsSalesQuantityRecordActionTypeEnum actionTypeEnum) {
    return actionRecordInputs.stream()
        .map(wmsStockActionRecordInput -> {
          return WmsSalesActionTypeRecordInput.builder()
              .actionType(actionTypeEnum.getCode())
              .quantity(wmsStockActionRecordInput.getQuantity())
              .objectId(wmsStockActionRecordInput.getObjectId())
              .build();
        })
        .collect(Collectors.toList());
  }

  /**
   * 回退增加与扣减操作库存.
   *
   * @param wmsApplication 仓库应用
   * @param batchSn 操作批次流水号
   * @return 回退操作批次流水号, 或空字符串,空字符串代表没有需要还原的操作
   */
  private String reverse0(WmsApplication wmsApplication, String batchSn) {
    AceAssertUtils.isEmpty(batchSn, "操作批次流水号不能为空");
    Long wmsAppId = wmsApplication.getId();
    List<WmsStockRecord> wmsStockRecords = this.wmsStockRecordManager.getByWmsAppIdAndBatchSnAndReverseFlagIsNoneAndActionTypeInAddSubtract(wmsAppId, batchSn);
    if (CollectionUtils.isEmpty(wmsStockRecords)) {
      return StringUtils.EMPTY;
    }
    String reverseBatchSn = this.wmsStockBatchRecordManager.getNewSn();
    WmsStockBatchRecord wmsStockBatchRecord = this.wmsStockBatchRecordManager.build(wmsAppId, reverseBatchSn);
    List<WmsStockRecord> reverseWmsStockRecords = this.wmsStockRecordManager.buildAddOrSubtractReverseRecord(reverseBatchSn, wmsStockRecords);
    List<Long> skuWmsStockIds = this.wmsStockRecordAggregateHelper.getStockIdsFromList(reverseWmsStockRecords);
    List<WmsStock> skuStockAndAllRecursionParentStocks = this.wmsStockManager.getSkuStockAndAllRecursionParentStocksByWmsAppIdAndSkuWmsStockIdIn(wmsAppId, skuWmsStockIds);
    this.wmsStockAggregate.reverseAndCalcRecursionParentStocks(skuStockAndAllRecursionParentStocks, wmsStockBatchRecord, reverseWmsStockRecords);
    return reverseBatchSn;
  }
}